package com.aaa.config;

import com.aaa.util.Result;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;
//     配置 表单的信息
    /**
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
       //
        http.formLogin()
                .loginProcessingUrl("/mylogin")// 登录的时候走的那个路径 就是/login
                .permitAll() // 放行action 对应的那个路径
                .successHandler((request, response, authentication) -> { // 认证成功的handler
                    //authentication  代表的是认证的信息
                    Result result = new Result(200,"成功",authentication);
                    printJsonData(response,result);

                })
                .failureHandler((request, response, exception) -> {// 认证失败的handler
                    Result result = new Result(500,"失败",null);
                    printJsonData(response,result);
                })
        ;

        // 按照角色授权
        http.authorizeRequests().antMatchers("/test/**").hasAnyRole("USER", "ADMIN");// ROLE_ADMIN ROLE_USER
//       http.authorizeRequests().antMatchers("/tab-menu/**").hasRole("ADMIN");

        //按照资源进行授权
        http.authorizeRequests().anyRequest().authenticated();// 其他的路径在访问这个系统的时候需要认证

        // 权限不足的时候 有异常  进入一个自定义的页面  403.html
       http.exceptionHandling().accessDeniedHandler((request, response, accessDeniedException) -> {
           Result result = new Result(403,"权限不允许",null);
           printJsonData(response,result);
       });

       // 退出的时候走的handler
        // 退出的时候  会把之前存的用户的信息清除掉
       http.logout().logoutUrl("/logout").logoutSuccessHandler((request, response, authentication) -> {
           Result result = new Result(200,"退出成功",authentication);
           printJsonData(response,result);
       });
       // 允许跨域
        http.cors();

        // html
        http.csrf().disable();// 关闭csrf的保护

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
     // 连接数据库
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }



    public void printJsonData(HttpServletResponse response,Object result){
        response.setContentType("application/json;charset=utf-8");// 响应的数据是一个json数据   字符编码格式是utf-8
        // result 转化为json字符串
        ObjectMapper objectMapper = new ObjectMapper();
        // 对象-.json字符串
        String s = null;
        try {
            s = objectMapper.writeValueAsString(result);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        writer.write(s);
        writer.flush();
        writer.close();

    }

}
